package daos

import (
	"bsm/constants"
	"bsm/logger"
	"bsm/models"
	"database/sql"
	"errors"
	"fmt"

	"github.com/jmoiron/sqlx"
)

type UserDao interface {
	Reset()
	// 开启一个工作单元（事务）
	Begin() error
	// 提交/回滚
	Commit() error
	Rollback() error
	InTransaction(fn func() error) error

	GetUserByCredentials(username, passwordHash string) (int, *models.ProjectUser)
	GetUserByUserID(userID string) (*models.ProjectUser, error)
	GetUsersByOrg(orgCode string) ([]models.ProjectUser, error)
	GetUserIdByName(orgcode string, name string) (int, error)
	GetUsersWithPagination(page, limit int, keyword string) ([]models.ProjectUser, int64, error)
	GetUserCount() (int64, error)
	AddUser(user *models.ProjectUser) error
	// GetSystemUser() ([]models.ProjectUser, error)
	GetOrgByCode(code string) (models.Org, error)
	GetScmOrg(orgCode string) (models.ScmOrg, error)

	DeleteUser(userID string) error
	CheckUserPassword(userID string, passwordHash string) (bool, error)
	UpdatePassword(userID string, newPassword string) error
	FreezeUser(userID string) error
	UnfreezeUser(userID string) error

	AddUserRole(userRole *models.UserRole) error
	DeleteUserRoles(userID string) error
	CheckUserRole(userID string, roleID string) (bool, error)
	GetUserWithRoles(userID string) (*models.UserWithRoles, error)
	GetRoles() ([]models.Role, error)

	UpdateUser(user *models.ProjectUser) error
}

type userDaoImpl struct {
	dbBsm *sqlx.DB
	txBsm *sqlx.Tx
}

func NewUserDao(dbBSM *sqlx.DB) UserDao {
	return &userDaoImpl{
		dbBsm: dbBSM,
		txBsm: nil,
	}
}

func (dao *userDaoImpl) Reset() {
	if dao.txBsm != nil {
		dao.Rollback() // 尝试回滚未完成的事务
	}
	dao.txBsm = nil // 确保状态清理
}

func (dao *userDaoImpl) Begin() error {
	if dao.txBsm != nil {
		return errors.New("事务已存在")
	}
	tx, err := dao.dbBsm.Beginx()
	if err != nil {
		return err
	}
	dao.txBsm = tx
	return nil
}

func (dao *userDaoImpl) Commit() error {
	if dao.txBsm == nil {
		return errors.New("没有活动的事务")
	}
	err := dao.txBsm.Commit()
	dao.txBsm = nil // 关键修复：提交后清理事务
	if err != nil {
		return fmt.Errorf("failed to commit pms transaction: %w", err)
	}
	return nil
}

func (dao *userDaoImpl) Rollback() error {
	if dao.txBsm == nil {
		return errors.New("没有活动的事务")
	}
	err := dao.txBsm.Rollback()
	dao.txBsm = nil // 关键修复：回滚后清理事务
	if err != nil {
		return fmt.Errorf("rollback errors: pms=%v", err)
	}
	return nil
}

// 事务模板方法（推荐）
func (d *userDaoImpl) InTransaction(fn func() error) error {
	if d.txBsm != nil {
		d.Rollback() // 清理已有事务
		return errors.New("事务已存在")
	}

	if err := d.Begin(); err != nil {
		return err
	}

	defer func() {
		if r := recover(); r != nil {
			d.Rollback()
			logger.Errorf("事务因panic回滚: %v", r)
		}
	}()

	if err := fn(); err != nil {
		d.Rollback()
		return err
	}

	return d.Commit()
}

func (ad *userDaoImpl) GetUserByCredentials(userid, passwordHash string) (int, *models.ProjectUser) {
	var query string
	var user models.ProjectUser
	query = `
		SELECT id, user_id, user_name, org_code 
		FROM bsm_user 
		WHERE user_id = ? LIMIT 1
	`
	err := ad.dbBsm.Get(&user, query, userid)
	if err != nil {
		if err == sql.ErrNoRows {
			logger.Warnf("GetUserByCredentials failed - user_id: %s, error: %s", userid, constants.LoginMessages[constants.LoginUserNotFound])
			return constants.LoginUserNotFound, nil // 用户不存在，不是错误
		}

		logger.Errorf("GetUserByCredentials failed - user_id: %s, error: %s", userid, constants.LoginMessages[constants.LoginServerError])
		return constants.LoginServerError, nil
	}

	query = `
		SELECT id, user_id, user_name, org_code,org_level,created_at,is_active
		FROM bsm_user 
		WHERE user_id = ? AND password = ?
		LIMIT 1
	`
	err = ad.dbBsm.Get(&user, query, userid, passwordHash)
	if err != nil {
		if err == sql.ErrNoRows {
			logger.Warnf("GetUserByCredentials failed - user_id: %s, error: %s", userid, constants.LoginMessages[constants.LoginPasswordError])
			logger.WithFields(map[string]interface{}{
				"layer":     "daos",
				"operation": "userDaoImpl-GetUserByCredentials",
				"user_id":   userid,
			}).Warnf("GetUserByCredentials failed - user_id: %s, error: 密码错误", userid)
			return constants.LoginPasswordError, nil // 密码错误
		}

		logger.Errorf("GetUserByCredentials failed - user_id: %s, error: %s", userid, constants.LoginMessages[constants.LoginServerError])
		logger.WithFields(map[string]interface{}{
			"layer":     "daos",
			"operation": "userDaoImpl-GetUserByCredentials",
			"user_id":   userid,
		}).Errorf("GetUserByCredentials failed - user_id: %s, error:服务器错误", userid)
		return constants.LoginServerError, nil
	}
	return constants.LoginSuccess, &user

	// 可以继续添加其他错误类型，如账号禁用、锁定等
}

func (dao *userDaoImpl) GetUserByUserID(userID string) (*models.ProjectUser, error) {
	var user []models.ProjectUser
	query := "select id,user_id,user_name,created_at,org_code,org_level from bsm_user where user_id=? "
	err := dao.dbBsm.Select(&user, query, userID)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, fmt.Errorf("user not found")
		}
		logger.Errorf("GetUserByID failed - userID: %s, error: %s", userID, err)
		return nil, fmt.Errorf("failed to get user: %v", err)
	}
	if len(user) == 0 {
		return nil, fmt.Errorf("user not found")
	}

	return &user[0], nil
}

func (dao *userDaoImpl) GetUsersByOrg(orgCode string) ([]models.ProjectUser, error) {
	const query = "SELECT id,user_id,user_name,org_code,org_level,created_at FROM bsm_user WHERE org_code=?"

	var users []models.ProjectUser
	err := dao.dbBsm.Select(&users, query, orgCode)
	if err != nil {
		logger.Errorf("GetUsersByOrg failed - orgCode: %s, error: %s", orgCode, err)
		return nil, err
	}
	return users, nil
}

func (id *userDaoImpl) GetUserIdByName(orgCode string, name string) (int, error) {
	var uid int
	err := id.dbBsm.QueryRow("SELECT id FROM bsm_user WHERE org_code=? and user_name=? ", orgCode, name).Scan(&uid)
	if err != nil {
		logger.Errorf("GetUserIdByName failed - orgCode: %s, name: %s, error: %s", orgCode, name, err)
		return 0, err
	}
	return uid, nil
}

// GetUsersWithPagination 分页获取用户列表
func (dao *userDaoImpl) GetUsersWithPagination(page, limit int, keyword string) ([]models.ProjectUser, int64, error) {
	var users []models.ProjectUser
	var total int64

	// 计算偏移量
	offset := (page - 1) * limit

	// 构建查询
	query := "SELECT id,user_id,user_name,created_at,org_code,org_level,is_active FROM bsm_user WHERE 1=1"
	countQuery := "SELECT COUNT(*) FROM bsm_user WHERE 1=1"

	if keyword != "" {
		query += " AND (user_id LIKE ? OR user_name LIKE ?)"
		countQuery += " AND (user_id LIKE ? OR user_name LIKE ?)"
		keyword = "%" + keyword + "%"
	}

	query += " LIMIT ? OFFSET ?"

	// 获取总数
	if keyword != "" {
		err := dao.dbBsm.Get(&total, countQuery, keyword, keyword)
		if err != nil {
			logger.Errorf("GetUsersWithPagination 获取总数 failed - page: %d, limit: %d, keyword: %s, error: %s", page, limit, keyword, err)
			return nil, 0, err
		}
	} else {
		err := dao.dbBsm.Get(&total, countQuery)
		if err != nil {
			logger.Errorf("GetUsersWithPagination 获取总数 failed - page: %d, limit: %d, error: %s", page, limit, err)
			return nil, 0, err
		}
	}

	// 获取数据
	if keyword != "" {
		err := dao.dbBsm.Select(&users, query, keyword, keyword, limit, offset)
		if err != nil {
			logger.Errorf("GetUsersWithPagination 获取数据 failed - page: %d, limit: %d, keyword: %s, error: %s", page, limit, keyword, err)
			return nil, 0, err
		}
	} else {
		err := dao.dbBsm.Select(&users, query, limit, offset)
		if err != nil {
			logger.Errorf("GetUsersWithPagination 获取数据 failed - page: %d, limit: %d, error: %s", page, limit, err)
			return nil, 0, err
		}
	}

	return users, total, nil
}

// GetUserCount 获取用户总数
func (dao *userDaoImpl) GetUserCount() (int64, error) {
	var count int64
	err := dao.dbBsm.Get(&count, "SELECT COUNT(*) FROM bsm_user")
	return count, err
}

func (dao *userDaoImpl) AddUser(user *models.ProjectUser) error {
	var query string
	query = "select org_level from bsm_org where org_code=?"
	var orgLevel int
	err := dao.dbBsm.Get(&orgLevel, query, user.OrgCode)
	if err != nil {
		logger.Errorf("AddUser failed - cannot get user org level: %v, error: %s", user, err)
		return fmt.Errorf("failed to get org level: %v", err)
	}
	user.OrgLevel = orgLevel

	query = "INSERT INTO bsm_user (user_id,user_name,password, org_code, org_level)  VALUES  (:user_id,:user_name,:password,:org_code,:org_level)"
	_, err = dao.dbBsm.NamedExec(query, user)
	if err != nil {
		logger.Errorf("AddUser failed - user: %v, error: %s", user, err)
		return fmt.Errorf("failed to add user: %v", err)
	}
	return nil
}

func (dao *userDaoImpl) GetScmOrg(orgcode string) (models.ScmOrg, error) {
	const query = "SELECT id,pkorg_outbound,pkorg_projectlib,pkorg_operatinglib,pkorg_reallib,ckname,org_code FROM bsm_org WHERE org_code=?"
	var org models.ScmOrg
	err := dao.dbBsm.Get(&org, query, orgcode)
	if err != nil {
		logger.Errorf("GetScmOrg failed - orgcode: %s, error: %s", orgcode, err)
		return models.ScmOrg{}, err
	}
	return org, nil
}

func (dao *userDaoImpl) GetOrgByCode(code string) (models.Org, error) {
	orgCode := code

	const query = "SELECT id,org_name,prefix,fullname,litename,org_inuse FROM bsm_org WHERE org_code=?"

	var org models.Org
	err := dao.dbBsm.Get(&org, query, orgCode)
	if err != nil {
		logger.Errorf("GetOrgByCode failed - code: %s, error: %s", code, err)
		return models.Org{}, err
	}
	return org, nil
}

func (dao *userDaoImpl) DeleteUser(userID string) error {
	const query = "DELETE FROM bsm_user WHERE user_id=?"
	_, err := dao.dbBsm.Exec(query, userID)
	if err != nil {
		logger.Errorf("DeleteUser failed - userID: %s, error: %s", userID, err)
		logger.WithFields(map[string]interface{}{
			"layer":     "dao",
			"operation": "userDaoImpl-DeleteUser",
		}).Errorf("DeleteUser failed - userID: %s, error: %s", userID, err)
		return fmt.Errorf("failed to delete user: %v", err)
	}
	return nil
}

// CheckUserPassword 检查用户密码是否正确
func (dao *userDaoImpl) CheckUserPassword(userID string, passwordHash string) (bool, error) {
	const query = "SELECT COUNT(*) FROM bsm_user WHERE user_id=? AND password=?"
	var count int64
	err := dao.dbBsm.Get(&count, query, userID, passwordHash)
	if err != nil {
		logger.Errorf("CheckUserPassword failed - userID: %s, error: %s", userID, err)
		return false, err
	}
	return count > 0, nil
}

func (dao *userDaoImpl) UpdatePassword(userID string, newPassword string) error {
	const query = "UPDATE bsm_user SET password=? WHERE user_id=?"
	_, err := dao.dbBsm.Exec(query, newPassword, userID)
	if err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "dao",
			"operation": "userDaoImpl-UpdatePassword",
		}).Errorf("UpdatePassword failed - userID: %s, error: %s", userID, err)
		return fmt.Errorf("failed to update password: %v", err)
	}
	return nil
}

// FreezeUser 冻结用户
func (dao *userDaoImpl) FreezeUser(userID string) error {
	const query = "UPDATE bsm_user SET is_active=0 WHERE user_id=?"
	_, err := dao.dbBsm.Exec(query, userID)
	if err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "dao",
			"operation": "userDaoImpl-FreezeUser",
		}).Errorf("FreezeUser failed - userID: %s, error: %s", userID, err)
		return fmt.Errorf("failed to freeze user: %v", err)
	}
	return nil
}

// UnfreezeUser 解冻用户
func (dao *userDaoImpl) UnfreezeUser(userID string) error {
	const query = "UPDATE bsm_user SET is_active=1 WHERE user_id=?"
	_, err := dao.dbBsm.Exec(query, userID)
	if err != nil {
		logger.WithFields(map[string]interface{}{
			"layer":     "dao",
			"operation": "userDaoImpl-UnfreezeUser",
		}).Errorf("UnfreezeUser failed - userID: %s, error: %s", userID, err)
		return fmt.Errorf("failed to unfreeze user: %v", err)
	}
	return nil
}

func (dao *userDaoImpl) AddUserRole(userRole *models.UserRole) error {
	const query = "INSERT INTO bsm_user_role (user_id,role_id)  VALUES  (:user_id,:role_id)"
	_, err := dao.dbBsm.NamedExec(query, userRole)
	if err != nil {
		logger.Errorf("AddUserRole failed - userRole: %v, error: %s", userRole, err)
		return fmt.Errorf("failed to add user role: %v", err)
	}
	return nil
}

func (dao *userDaoImpl) CheckUserRole(userID string, roleID string) (bool, error) {
	const query = "SELECT COUNT(*) FROM bsm_user_role WHERE user_id=? AND role_id=?"
	var count int64
	err := dao.dbBsm.Get(&count, query, userID, roleID)
	if err != nil {
		logger.Errorf("CheckUserRole failed - userID: %s, roleID: %s, error: %s", userID, roleID, err)
		return false, err
	}
	return count > 0, nil
}

func (dao *userDaoImpl) GetUserWithRoles(userID string) (*models.UserWithRoles, error) {
	// 获取用户基本信息
	user, err := dao.GetUserByUserID(userID)
	if err != nil || user == nil {
		return nil, err
	}

	// 获取用户角色 (简化查询，不需要JOIN)
	roleQuery := `
		SELECT r.role_id, r.role_name, r.description, r.status 
		FROM bsm_role r
		INNER JOIN bsm_user_role ur ON r.role_id = ur.role_id
		WHERE ur.user_id = ? AND r.status = 1`

	var roles []models.Role
	err = dao.dbBsm.Select(&roles, roleQuery, userID)
	if err != nil {
		return nil, err
	}

	return &models.UserWithRoles{
		ProjectUser: *user,
		Roles:       roles,
	}, nil
}

func (dao *userDaoImpl) GetRoles() ([]models.Role, error) {
	const query = "SELECT role_id, role_name, description, status FROM bsm_role WHERE status = 1"
	var roles []models.Role
	err := dao.dbBsm.Select(&roles, query)
	if err != nil {
		if err == sql.ErrNoRows {
			return nil, nil
		}
		logger.Errorf("GetRoles failed - error: %s", err)
		return nil, err
	}
	return roles, nil
}

func (dao *userDaoImpl) DeleteUserRoles(userID string) error {
	const query = "DELETE FROM bsm_user_role WHERE user_id=?"
	_, err := dao.dbBsm.Exec(query, userID)
	if err != nil {
		logger.Errorf("DeleteUserRoles failed - userID: %s, error: %s", userID, err)
		return fmt.Errorf("failed to delete user roles: %v", err)
	}
	return nil
}

func (dao *userDaoImpl) UpdateUser(user *models.ProjectUser) error {
	const query = "UPDATE bsm_user SET user_name=?, org_code=?, org_level=? WHERE user_id=?"
	_, err := dao.dbBsm.Exec(query, user.UserName, user.OrgCode, user.OrgLevel, user.UserID)
	if err != nil {
		logger.Errorf("UpdateUser failed - user: %v, error: %s", user, err)
		return fmt.Errorf("failed to update user: %v", err)
	}
	return nil
}
